#include <tT.h>
#include <env.h>

#include "adc.h"


env_result_t adc_init(adc_t *self, void *none)
{
  ENV_DEBUG("enter adc_init()\r\n");
  /* Power up the ADC unit */	
  SC->PCONP |= (1<<12);
  ADC->ADCR =  0;
  
  /* Clock select 00 = CCLK/4 01 = CCLK 10 = CCLk/2 11 = CCLK/8	*/
  SC->PCLKSEL0 &= ~(3<<24);
  SC->PCLKSEL0 |= (3<<24);
	
  
  
  /* Select pin functions */
  PINCON->PINSEL1 |= 	(1<<14) |	/** ADC00 - Temp */
											(1<<16) |	/** ADC01 - Voltage */
											(1<<18) |	/** ADC02 - Current U+ */
											(1<<20);	/** ADC03 - Current U- */
  
  PINCON->PINSEL3 |= 	(3<<28) |	/** ADC04 - Current V+ */
											(3<<30);	/** ADC05 - Current V- */
			
  PINCON->PINSEL0 |= 	(2<<6) |	/** ADC06 - Current GND+ */
											(2<<4);		/** ADC07 - Current GND- */
	  
  return 0;
}

env_result_t adc_start_burst(adc_t *self, void *none)
{
	ADC->ADINTEN = (1<<7);
 /* adc operational @ 12,5MHz. conversion rate = 192kHz
  * ad0:7 selected for burstmode conversion. p.574 */
  ADC->ADCR |= (1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<4) | (1<<5) | (1<<6) | (1<<7) | (1<<16) | (1<<21);
  
  NVIC_EnableIRQ(ADC_IRQn);
	
  NVIC_SetPriority(ADC_IRQn, 31);
  
  return 0;
}

env_result_t adc_calibrate(adc_t *self, uint32_t i)
{
	int32_t calib = 0;
	uint32_t j;
	
	// dummy conversion to clear the inner cap
	ADC->ADGDR; // Clear register
	ADC->ADCR = (1<<i) | (1<<21) | (1<<24);
	while ( !(ADC->ADGDR & (1<<31))) ;
	ADC->ADGDR; // Clear register
	
	
	
	//ENV_DEBUG("enter adc_calibrate()\r\n");
	for ( j = 0 ; j < 8 ; j++)
	{
		ADC->ADCR = (1<<i) | (1<<21) | (1<<24);
		while ( !(ADC->ADGDR & (1<<31))) ;
		
		calib += ((ADC->ADGDR>>4) & 0x00000FFF);
	}
	self->offset[i] = calib/8;
	
	ENV_DEBUG("ADC");
	env_send(i);
	ENV_DEBUG(" offset= ");
	env_send(self->offset[i]);
	ENV_DEBUG("\r\n");
	
	return 0;
}

env_result_t adc_send(uint32_t val)
{
  if (val < 0 ) 
  {
    val = -val;
    ENV_DEBUG("-");
  }
  if ((val / 10) > 0) {
    adc_send(val / 10);
  }
  
  
    while ((UART1->FIFOLVL & (0xf << 8)) == (0xf << 8)) 
    {
			/* Busy wait for buffer space to become free. */
    }
    
    UART1->THR = (val%10) + '0';
    
    
  return 0;
}

/** Interrupt will run every time AD07 is done converting (@32kHz) */

void ADC_IRQHandler(void)
{
	adc.raw[7] = ((ADC->ADDR7>>4) & 0x00000FFF); // read this first to clear the interrupt flag.
	
  //Bit shift 4 becouse result is 4 bits in the word.
  adc.raw[0] = ((ADC->ADDR0>>4) & 0x00000FFF);
  adc.raw[1] = ((ADC->ADDR1>>4) & 0x00000FFF);
  adc.raw[2] = ((ADC->ADDR2>>4) & 0x00000FFF);
  adc.raw[3] = ((ADC->ADDR3>>4) & 0x00000FFF);
  adc.raw[4] = ((ADC->ADDR4>>4) & 0x00000FFF);
  adc.raw[5] = ((ADC->ADDR5>>4) & 0x00000FFF);
  adc.raw[6] = ((ADC->ADDR6>>4) & 0x00000FFF);
  
  

  
  //tt_interrupt_mark();
  //TT_SYNC(&adc, adc_send, TT_ARGS_NONE);
  //tt_schedule(1);
  //adc_send(adc.ad[5]);
  //ENV_DEBUG("\r\n");
}
